package com.example.android.quakereport;

import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 * Helper methods related to requesting and receiving earthquake data from USGS.
 */
public final class QueryUtils {

    //Tag for the log message
    public static final String LOG_TAG = QueryUtils.class.getSimpleName();

    /**
     * Create a private constructor because no one should ever create a {@link QueryUtils} object.
     * This class is only meant to hold static variables and methods, which can be accessed
     * directly from the class name QueryUtils (and an object instance of QueryUtils is not needed).
     */
    private QueryUtils() {
    }

    public static ArrayList<Earthquake> fetchEarthquakeData(String requestUrl) {
        //Create the URL object
        URL url = createUrl(requestUrl);

        //Perform HTTP request to the URL and receive a JSON response back
        String jsonResponse = null;
        try {
            jsonResponse = makeHttpResponse(url);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error ");
        }

        //Extract relevant fields from JSON response and create an ArrayList<Earthquake> object
        ArrayList<Earthquake> earthquakes = extractEarthquakes(jsonResponse);
        return earthquakes;
    }

    /**
     *
     * @param stringUrl is the input of the stringUrl
     * @return the new URL Object from the given string URL
     */
    private static URL createUrl(String stringUrl) {
        URL url = null;
        try {
            //generate the URL of the input stringUrl.
            url = new URL(stringUrl);
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "Error with creating URL", e);
        }

        return url;
    }

    /**
     * Make an HTTP request to the given URL and return a String as the response
     * @param url is the input URL Object
     * @return a String as the response
     * @throws IOException e
     */
    private static String makeHttpResponse(URL url) throws IOException {
        String jsonResponse = "";

        //if the url is null, then return early.
        if (url == null) {
            return jsonResponse;
        }

        HttpURLConnection urlConnection = null;
        InputStream inputStream = null;
        try {
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setConnectTimeout(15000);
            urlConnection.setReadTimeout(10000);
            urlConnection.connect();
            //Use urlConnection.getResponseCode() to check the code,
            //If the request was successful (response code is 200),
            //then read the input stream and parse the response
            if (urlConnection.getResponseCode() == 200) {
                inputStream = urlConnection.getInputStream();
                jsonResponse = readFromStream(inputStream);
            } else {
                Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
            }
        } catch (IOException e) {
            //Handle the exception
            Log.e(LOG_TAG, "problem retrieving the earthquake JSON result.", e);
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return jsonResponse;
    }

    /**
     * Convert the{@link InputStream} into a String which contains the
     * whole JSON response from the server
     * @param inputStream is the input stream from the HTTPResponse
     * @return a String of the JSON response
     * @throws IOException
     */
    public static String readFromStream(InputStream inputStream) throws IOException {
        StringBuilder output = new StringBuilder();
        if (inputStream != null) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
            BufferedReader reader = new BufferedReader(inputStreamReader);
            String line = reader.readLine();
            while (line != null) {
                output.append(line);
                line = reader.readLine();
            }
        }
        return output.toString();
    }



    /**
     * Return a list of {@link Earthquake} objects that has been built up from
     * parsing a JSON response.
     */
    public static ArrayList<Earthquake> extractEarthquakes(String earthquakeJSON) {

        // Create an empty ArrayList that we can start adding earthquakes to
        ArrayList<Earthquake> earthquakes = new ArrayList<Earthquake>();

        // Try to parse the SAMPLE_JSON_RESPONSE. If there's a problem with the way the JSON
        // is formatted, a JSONException exception object will be thrown.
        // Catch the exception so the app doesn't crash, and print the error message to the logs.
        try {
            // TODO: Parse the response given by the SAMPLE_JSON_RESPONSE string and
            // build up a list of Earthquake objects with the corresponding data.
            JSONObject jsonRootObject = new JSONObject(earthquakeJSON);
            JSONArray jsonArray = jsonRootObject.getJSONArray("features");

            for (int i = 0; i < jsonArray.length(); i++){
                JSONObject jsonEarthquakeObject = jsonArray.getJSONObject(i);
                JSONObject jsonPropertiesObject = jsonEarthquakeObject.getJSONObject("properties");
                Double magnitude = jsonPropertiesObject.getDouble("mag");
                String place = jsonPropertiesObject.getString("place");
                String url = jsonPropertiesObject.getString("url");

                //long time = Long.parseLong(jsonPropertiesObject.getString("time"));
                long time = jsonPropertiesObject.getLong("time");
                earthquakes.add(new Earthquake(magnitude, place, time, url));
            }

        } catch (JSONException e) {
            // If an error is thrown when executing any of the above statements in the "try" block,
            // catch the exception here, so the app doesn't crash. Print a log message
            // with the message from the exception.
            Log.e("QueryUtils", "Problem parsing the earthquake JSON results", e);
        }

        // Return the list of earthquakes
        return earthquakes;
    }

}